/**
 Created by:
 muhtearjan mehmood مۇختەرجان مەخمۇت (Email: yeganaaa@163.com)
 At 8/19/20 2:36 AM
 */
import {IStateManager, RpcServer, State} from "./RpcServer";

export class StateManagerInMemory<STATE extends State> implements IStateManager<STATE> {
    server: RpcServer<any, any, STATE> = null!
    private _innerState = new Map<string, {state: STATE, time: number}>()
    private _sweepTimeId: NodeJS.Timeout = null!;
    constructor(private expireMilliSeconds = 1000 * 60 * 30) {
    }

    public async clear(stateId: string): Promise<boolean> {
        return this._innerState.delete(stateId)
    }

    public async clearAll(): Promise<void> {
        this._innerState.clear()
    }

    public async get(stateId: string): Promise<STATE> {
        const result = this._innerState.get(stateId)
        if (result == null) throw Error("State not found.")
        result.time = Date.now()
        return result.state
    }

    public async getAll(): Promise<STATE[]> {
        return [...this._innerState.values()].map(value => value.state)
    }

    public async has(stateId: string): Promise<boolean> {
        return this._innerState.has(stateId)
    }

    public async initialize(): Promise<void> {
        this._sweepTimeId = setInterval(() => {
            this._innerState.forEach((state, key) => {
                const expired = Date.now() - state.time > this.expireMilliSeconds
                if (expired) this.clear(state.state.id)
            })
        }, this.expireMilliSeconds)
    }

    public async dispose(): Promise<void> {
        clearInterval(this._sweepTimeId)
    }

    public async save(state: STATE): Promise<void> {
        this._innerState.set(state.id, {
            state: state,
            time: Date.now()
        })
    }
}
